package com.demo.tx.seata.service.tcc.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.miya.controller.client.SeataMiyaClient;
import com.demo.tx.seata.dao.mapper.UserMapper;
import com.demo.tx.seata.model.entity.User;
import com.demo.tx.seata.service.tcc.SeataTCCRemoteService;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class SeataTCCRemoteServiceImpl extends ServiceImpl<UserMapper, User> implements SeataTCCRemoteService {

    @Resource
    private SeataMiyaClient seataMiyaClient;

    /**
     * 远程调用，测试第三方使用TCC事务模式
     *
     * @param userId 用户id
     * @param sleepTime 睡眠时间
     * @throws InterruptedException 异常
     */
    @Override
    public void prepare(BusinessActionContext actionContext,
                        @BusinessActionContextParameter(paramName = "userId") Long userId,
                        @BusinessActionContextParameter(paramName = "sleepTime") Long sleepTime) throws InterruptedException {
        User user = new User().setUserName("tcc-tx-" + sleepTime).setUserId(userId);
        this.save(user);

        seataMiyaClient.prepare(userId, sleepTime);
        seataMiyaClient.prepare(userId + 1, sleepTime + 5);
    }

    @Override
    public boolean commitMethod(BusinessActionContext actionContext) {
        long currentedTimeMillis = System.currentTimeMillis();
        log.info("用户 {}, 更新创建时间 {}", actionContext.getActionContext("userId"), currentedTimeMillis);

        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(User::getCreateTime, currentedTimeMillis);
        wrapper.eq(User::getUserId, actionContext.getActionContext("userId"));
        this.update(wrapper);
        return true;
    }

    @Override
    public boolean rollbackMethod(BusinessActionContext parameterContext) {
        Integer userId = (Integer) parameterContext.getActionContext("userId");
        log.info("用户 {} 回滚", userId);
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(User::getUserName, "tcc-tx-rollback-" + parameterContext.getActionContext("sleepTime"));
        wrapper.eq(User::getUserId, userId);
        this.update(wrapper);
        return true;
    }
}
